package de.mmis.core.publishsubscribe;

import java.util.HashMap;

import de.mmis.core.base.Pair;
import de.mmis.core.base.abstracttree.Tree;
import de.mmis.core.publishsubscribe.filter.AtomicFilter;
import de.mmis.core.publishsubscribe.filter.BooleanOperator;
import de.mmis.core.publishsubscribe.filter.CompoundFilter;
import de.mmis.core.publishsubscribe.filter.Filter;
import de.mmis.core.publishsubscribe.filter.FilterOperator;
import de.mmis.core.publishsubscribe.filter.FilterValue;

class FilterHelper {

	private FilterHelper() {
		// hide constructor
	}

	static class ExtractResult {
		HashMap<Filter, Pair<String, String>> worldstateFilter = new HashMap<Filter, Pair<String, String>>();
	}

	private static void addFromFilterValue(FilterValue value,
			ExtractResult result) {
		if (value.getId() == null)
			return;

		Pair<String, String> pair = new Pair<String, String>(value.getId(),
				value.getKey());

		Filter sender = new AtomicFilter(FilterOperator.EQUAL, new FilterValue(
				":sender"), new FilterValue(Tree.fromObject(pair.getFirst())));
		Filter key = new AtomicFilter(pair.getSecond());
		Filter filter = new CompoundFilter(BooleanOperator.AND, sender, key);

		result.worldstateFilter.put(filter, pair);
	}

	/**
	 * Returns a set of {@link Filter}s of the form
	 * <code>:sender == ID && key</code>. The Filters are constructed for each
	 * Worldstate {@link FilterValue}.
	 * 
	 * @param filter
	 * @return
	 */
	static ExtractResult extractWorldstateFilter(Filter filter) {
		ExtractResult result = new ExtractResult();

		if (filter == null)
			return result;

		if (filter instanceof AtomicFilter) {
			AtomicFilter f = (AtomicFilter) filter;

			if (f.getOp() != null) {
				addFromFilterValue(f.getValue1(), result);
				addFromFilterValue(f.getValue2(), result);
			}

			return result;
		}

		CompoundFilter f = (CompoundFilter) filter;

		if (f.getOp() == null) {
			// negate
			return extractWorldstateFilter(f.getFilter1());
		}

		ExtractResult result1 = extractWorldstateFilter(f.getFilter1());
		ExtractResult result2 = extractWorldstateFilter(f.getFilter2());

		result.worldstateFilter.putAll(result1.worldstateFilter);
		result.worldstateFilter.putAll(result2.worldstateFilter);

		return result;
	}
}
